ON ERROR Statement ---------------------------------------------------------------------------- Action Enables an error-handling routine and specifies the location of that routine in the program. The ON ERROR statement also can be used to disable an error-handling routine. Syntax ON LOCAL ERROR { GOTO line | RESUME NEXT | GOTO 0} Remarks If no ON ERROR statement is used in a program, any run-time error will be fatal (BASIC generates an error message and program execution stops). The following list describes the parts of the ON ERROR statement. ----------------------------------------------------------------------------- Part Description ---------------------------------------------------------------------------- LOCAL Used to indicate an error-handling routine in the same procedure. If not used, module-level error handlers are indicated. Part Description ---------------------------------------------------------------------------- handlers are indicated. GOTO line Enables the error-handling routine that starts at line. Thereafter, if a run-time error occurs, program control branches to line (a label or a line number). The specified line is either in the module-level code or in the same procedure (if the LOCAL keyword is used). If not found in either place, BASIC generates a Label not defined compile-time error. RESUME NEXT Specifies that, when a run-time error occurs, control goes to the statement after the statement where the error occurred; the ERR function then can be used to Part Description ---------------------------------------------------------------------------- function then can be used to obtain the run-time error code. GOTO 0 Disables any enabled module-level error-handling routine within the current module, or disables any enabled error handler within the current procedure (if used together with the LOCAL keyword). The LOCAL keyword indicates an error-handling routine that is "local" to the procedure within which the error-handling routine is located. A local error-handling routine. - Overrides any enabled module-level error-handling routines. - Is enabled only while the procedure within which it is located is executing. Notice that the local error handler remains enabled while any procedures execute that are directly or indirectly called by the procedure within which the error handler is located. One of those procedures may supersede the local error handler. Note The module-level error-handling routines provided by previous versions of BASIC may be all you need; you may never need to use the LOCAL keyword. Use of the RESUME NEXT option causes program execution to resume with the statement immediately following the statement that caused the run-time error. This enables your program to continue execution of a block of program code, despite a run-time error, then check for the cause of the error. This also enables you to build the error-handling code in line with the main module code or procedure, rather than at a remote location in the program. The statement form ON ERROR GOTO 0 disables error handling. It does not specify line 0 as the start of the error-handling code, even if the program or procedure contains a line num-bered 0. Notice that an error-handling routine is not a SUB or FUNCTION procedure or a DEF FN function. An error-handling routine is a block of code marked by a line label or line number. An error handler is enabled when it is referred to by an ON ERROR GOTO line statement. Once an error handler is enabled, a run-time error causes program control to jump to the enabled error-handling routine and makes the error handler "active." An error handler is active from the time a run-time error has been trapped until a RESUME statement is executed in the handler. Error-handling routines must rely on the value in ERR to determine the cause of the error. The error-handling routine should test or save this value before any other error can occur or before calling a procedure that could cause an error. The value in ERR reflects only the last error to occur. If you use the BASIC command line to compile a program that has been developed in the QBX environment and has error-handling routines, compile with the -E or -X option. The Make EXE File command in the QBX environment uses these options. If an error occurs in a procedure or module that does not have an enabled error-handling routine, BASIC searches for an enabled, inactive error handler to trap the error. BASIC searches back through all the procedures and modules that have called the procedure where the error occurred. Using Module-Level Error Handlers Once enabled by execution of an ON ERROR GOTO line statement, a module-level error handler stays enabled unless explicitly disabled by execution of an ON ERROR GOTO 0 statement somewhere in the module. In the following cases, BASIC searches back through the module-level code of the calling modules, looking for an enabled, inactive error handler. - In a multiple-module program that contains only module-level error handlers, if an enabled and inactive error handler cannot be found in the module where the error occurred. - If an error occurs in a module-level error handler itself (BASIC does not automatically treat this as a fatal error). - If an ON ERROR GOTO 0 statement is encountered while the current module's module-level error handler is active. Procedure-Level Error Handlers SUB and FUNCTION procedures and DEF FN functions can contain their own error-handling routines. To enable a local error handler, use the statement ON LOCAL ERROR GOTO line. The argument line must be a label or line number in the same procedure as the ON LOCAL ERROR GOTO statement. The local error handler is automatically disabled when the procedure returns, or by execution of the statement ON LOCAL ERROR GOTO 0. You will want program flow to avoid the statements that make up the error-handling routine. One way to keep the error-handling code from executing when there is no error is to place an EXIT SUB, EXIT FUNCTION, or EXIT DEF statement immediately ahead of the error-handling routine, as in the following example. SUB InitializeMatrix (var1, var2, var3, var4) . . . ON LOCAL ERROR GOTO ErrorHandler . . . EXIT SUB ErrorHandler. . . . RESUME NEXT END SUB The example shows the error-handling code located after the EXIT SUB statement and before the END SUB statement. This partitions the error-handling code from the normal execution flow of the procedure. However, error-handling code can be placed anywhere in a procedure. In the QBX environment, or if the command-line compiler is used with the -O option. - If a local error handler is active and an END SUB, END FUNCTION, or END DEF statement is encountered, BASIC generates the run-time error message No RESUME. - If an EXIT SUB, EXIT FUNCTION, or EXIT DEF statement is encountered, BASIC does not generate a run-time error; in other words, it is assumed that this does not represent a logic error in the program. In a multiple-module program that contains only procedure-level (local) error handlers, if an enabled and inactive error handler cannot be found in the procedure where the error occurred, BASIC searches back through all the calling procedures as well as the module-level code of all the calling modules, looking for an enabled, inactive error handler. Using Both Module-Level and Procedure-Level Error Handlers For simplicity and clarity, avoid using both local- and module-level error handlers in the same program, except for using an error handler in the main module module-level code as the last line of defense against a fatal error. If you need to, however, you can have both a module-level error handler and a local error handler enabled at the same time. (In fact, you can enable both local- and module-level error handling from within a procedure.) While searching for an enabled, inactive error handler, BASIC may encounter an active event handler. Unless an enabled error-handling routine is provided in the same module-level code as the event handler, BASIC generates a fatal error. Therefore, to produce completely bullet-proof BASIC code in programs that trap events, make sure an error handler in the same module-level code as the event handler is enabled at the time the event occurs. Because event handlers can be located only at the module level, this is another special case where you might mix module-level and procedure-level error handlers. Notice that when an error-handling routine is finished and program execution resumes through execution of a RESUME 0 or RESUME NEXT statement, the resume location is based on the location of the error-handling routine, and not necessarily on the location where the error occurred. For more information, see the entry for RESUME. See Also ERL, ERR; ERROR; RESUME Example The following program prompts the user for a disk drive designation. Once the user has input the drive designation, the program attempts to write a large file to the disk. A number of errors can occur. DECLARE SUB ErrorMessage (Message$) DECLARE SUB WriteBigFile (Filenum%) ON ERROR GOTO ErrHandler CLS PRINT "This program will attempt to write a large file to a disk drive that" PRINT "you have selected. The file will be erased when the program ends." PRINT DO INPUT "Enter the letter of the drive where you want this file written"; DR$ DR$ = UCASE$(DR$) LOOP UNTIL LEN(DR$) >= 1 AND LEN(DR$) <= 2 AND DR$ >= "A" AND DR$ <= "Z" IF LEN(DR$) > 1 THEN IF RIGHT$(DR$, 1) <> "." THEN DR$ = LEFT$(DR$, 1) + "." END IF ELSE DR$ = DR$ + "." END IF ' Put together a complete file specification. FileSpec$ = DR$ + "BIGFILE.XXX" ' Get the next available file number. Filenum% = FREEFILE ' Try an open the file OPEN FileSpec$ FOR OUTPUT AS Filenum% WriteBigFile Filenum% CLOSE Filenum% CLS PRINT "Everything was OK. No errors occurred." PRINT "Deleting the file that was created." KILL FileSpec$ ' Same as END, returns to operating system. SYSTEM ErrHandler. SELECT CASE ERR CASE 52'Bad file name or number. END CASE 53' File not found. RESUME NEXT CASE 57' Device I-O error. ErrorMessage "You should probably format the disk." END CASE 64' Bad file name. ErrorMessage "The drive name you specified was not correct." END CASE 68' Device unavailable ErrorMessage "The drive you named is unavailable." END CASE 71' Drive not ready ErrorMessage "The drive was not ready. Check the drive!" END CASE ELSE ErrorMessage "An unexpected FATAL error has occurred." STOP END SELECT SUB ErrorMessage (Message$) ON LOCAL ERROR GOTO MessageError CLS PRINT Message$ PRINT "Cannot continue." PRINT PRINT "Press any key to exit." DO LOOP WHILE INKEY$ = "" EXIT SUB MessageError. RESUME NEXT END SUB SUB WriteBigFile (Filenum%) ON LOCAL ERROR GOTO LocalHandler TEXT$ = STRING$(1024, "A") FOR I% = 1 TO 400 PRINT #Filenum%, TEXT$ NEXT I% EXIT SUB LocalHandler. SELECT CASE ERR CASE 61 ' Disk full ErrorMessage ("There is no room remaining on the disk.") KILL "BIGFILE.XXX" END CASE ELSE ERROR ERR END SELECT END SUB